package cn.com.selfsoft.smartcity.core.service;

import cn.com.self.apis.member.entity.vo.UMemberInfoVO;
import cn.com.self.apis.portal.util.CustomPage;
import cn.com.self.apis.portal.util.ICustomPage;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.com.selfsoft.smartcity.commons.entity.AbstractEntity;
import cn.com.selfsoft.smartcity.commons.exception.EntityNotFoundException;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

/**
 * @param <T>
 * @param <K>
 */
public abstract class BaseServiceImpl<T, K extends Serializable> extends GenericServiceImpl<T, K, T> {

    @Autowired
    protected BaseMapper<T> baseMapper;

    public BaseMapper<T> getBaseMapper() {
        return baseMapper;
    }

    protected void setBaseMapper(BaseMapper<T> baseMapper) {
        this.baseMapper = baseMapper;
    }

    @Override
    public long count(Map<String, Object> parameterMap) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        parameterMap.forEach((key, value) ->
                queryWrapper.like(key, value)
        );
        return this.baseMapper.selectCount(queryWrapper);
    }


    @Override
    public ICustomPage<T> page(Map<String, Object> parameterMap, Pageable page) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        parameterMap.forEach((key, value) ->
                queryWrapper.like(key, value)
        );
        page.getSort().get().forEach((order) -> {
            if (order.getDirection().isDescending()) {
                queryWrapper.orderByDesc(order.getProperty());
            } else {
                queryWrapper.orderByAsc(order.getProperty());
            }
        });
        IPage<T> entityPage = this.baseMapper.selectPage(convertPage(page), queryWrapper);
//        List<T> content=(List<T>)entityPage..getRows();
//        return new PageImpl<>(content, createSuitablePage(page), entityPage.getTotal());
        CustomPage<T> customPage = new CustomPage<>();
        BeanUtils.copyProperties(entityPage, customPage);

        return customPage;
    }

    public ICustomPage<T> copyProperties(IPage<T> entityPage){
        CustomPage<T> page = new CustomPage<>();
        BeanUtils.copyProperties(entityPage, page);
        return page;
    }

    @Override
    public Page<T> page(T entity, Pageable page) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        try {
            PropertyUtils.describe(entity).entrySet().forEach(entry -> {
                if (!entry.getKey().equals("class")) {
                    queryWrapper.eq(entry.getKey(), entry.getValue());
                }
            });
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {

        }
        page.getSort().get().forEach((order) -> {
            if (order.getDirection().isDescending()) {
                queryWrapper.orderByDesc(order.getProperty());
            } else {
                queryWrapper.orderByAsc(order.getProperty());
            }
        });
        IPage<T> entityPage = this.baseMapper.selectPage(convertPage(page), queryWrapper);
        return new PageImpl<>(entityPage.getRecords(), createSuitablePage(page), entityPage.getTotal());
    }

    @Override
    public List<T> list(Map<String, Object> parameterMap, Sort sort) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        parameterMap.forEach((key, value) ->
                queryWrapper.eq(key, value)
        );
        sort.get().forEach((order) -> {
            if (order.getDirection().isDescending()) {
                queryWrapper.orderByDesc(order.getProperty());
            } else {
                queryWrapper.orderByAsc(order.getProperty());
            }
        });
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<T> list(T entity, Sort sort) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        try {
            PropertyUtils.describe(entity).entrySet().forEach(entry -> {
                if (!entry.getKey().equals("class")) {
                    queryWrapper.eq(entry.getKey(), entry.getValue());
                }
            });
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {

        }
        sort.get().forEach((order) -> {
            if (order.getDirection().isDescending()) {
                queryWrapper.orderByDesc(order.getProperty());
            } else {
                queryWrapper.orderByAsc(order.getProperty());
            }
        });
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public T load(K id) {
        return this.baseMapper.selectById(id);
    }

    @Override
    public void delete(K id) throws EntityNotFoundException {
        T t = this.baseMapper.selectById(id);
        if (null != t) {
            this.baseMapper.deleteById(id);
        } else {
            throw new EntityNotFoundException("需要删除的资源不存在");
        }
    }


    @Override
    public T create(T entity, String... ignoreProperties) {
        this.baseMapper.insert(entity);
        return entity;
    }

    @Override
    public T update(T entity, String... ignoreProperties) throws EntityNotFoundException {
        T t = this.baseMapper.selectById(((AbstractEntity) entity).getId());
        if (null != t) {
            this.baseMapper.updateById(entity);
            return entity;
        } else {
            throw new EntityNotFoundException("需要更新的资源不存在");
        }
    }

    /**
     * Pageable转IPage
     *
     * @param pageable
     * @return
     */
    protected IPage<T> convertPage(Pageable pageable) {
        IPage<T> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>();
        page.setCurrent(pageable.getPageNumber());
        page.setSize(pageable.getPageSize());
        return page;
    }

    /**
     * 创建以第0页为第1页的分页对象
     *
     * @param pageable
     * @return
     */
    protected Pageable createSuitablePage(Pageable pageable) {
        if (0 == pageable.getPageNumber()) {
            return pageable;
        } else {
            return PageRequest.of(pageable.getPageNumber() - 1, pageable.getPageSize());
        }
    }
}
